/**
 * 
 */
package com.hexacta.hrs.repositories.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.vectrics.employee.Employee;
import org.vectrics.recruiter.job.JobFunction;

import com.hexacta.hrs.domain.feedback.Feedback;
import com.hexacta.hrs.domain.feedback.FeedbackPeriod;
import com.hexacta.hrs.domain.feedback.Period;
import com.hexacta.hrs.repositories.feedback.FeedbackRepository;

/**
 * @author gvilla
 * 
 */
public class FeedbackRecordObjectRepository extends HibernateRecordObjectRepository<Feedback> implements
        FeedbackRepository {

    /**
     * @param entityClass
     */
    public FeedbackRecordObjectRepository(final Class<Feedback> entityClass) {
        super(entityClass);
        // TODO Auto-generated constructor stub
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.hexacta.hrs.repositories.RecordObjectRepository#matching(org.vectrics
     * .common.db.RecordObject)
     */
    @Override
    public Collection<Feedback> matching(final Feedback criteria) {
        // TODO Auto-generated method stub
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.hexacta.hrs.repositories.feedback.FeedbackRepository#getOpen()
     */
    @SuppressWarnings("unchecked")
    @Override
    public Collection<Feedback> getOpen() {
        String query = "select fp.feedbacks from " + FeedbackPeriod.class.getName() + " fp"
                + " where fp.closed = false";

        List<Feedback> feedbacks = this.getSession().createQuery(query).list();

        return feedbacks;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.hexacta.hrs.repositories.feedback.FeedbackRepository#getWith(org.
     * vectrics.employee.Employee, org.vectrics.employee.Employee,
     * org.vectrics.recruiter.job.JobFunction)
     */
    @SuppressWarnings("unchecked")
    @Override
    public Collection<Feedback> getWith(final Employee employee, final Employee mentor, final JobFunction role) {

        String query = "select feedbacks from " + FeedbackPeriod.class.getName() + " where closed = false";

        if (employee != null) {
            query += " and employee.id = " + employee.getId();
        }
        if (mentor != null) {
            query += " and employee.mentor.id = " + mentor.getId();
        }
        if (role != null) {
            query += " and employee.function.code = " + role.getCode();
        }

        List<Feedback> feedbacks = this.getSession().createQuery(query).list();

        return feedbacks;
    }

    @Override
    public Collection<Employee> findAllEvaluators() {
        Query query = getSession().createQuery(
                "SELECT DISTINCT f.reporter FROM " + Feedback.class.getName() + " f "
                        + "WHERE f.reporter.dateEnd IS NULL");
        return query.list();
    }

    @Override
    public Collection<Feedback> findFeedbacksWithCriteria(final String period, final Long employeeIdCurrentUser,
            final Integer jobFunctionWeightCurrentUser, final Long employeeId, final Long projectId,
            final String roleId, final Long mentorId, final Long evaluatorId) {

        if (jobFunctionWeightCurrentUser == null)
            return new ArrayList<Feedback>();
        Criteria crit = getSession().createCriteria(Feedback.class, "feedback");
        crit.add(Restrictions.eq("period", period));

        Criteria critEmp = crit.createCriteria("evaluated");

        // Solo debe traer los empleados con menor seniority que el usuario
        // logueado.
        Criteria critFunctionEmp = critEmp.createCriteria("function");
        critFunctionEmp.add(Restrictions.lt("weight", jobFunctionWeightCurrentUser));

        if (employeeId != null) {
            crit.add(Restrictions.eq("feedback.evaluated.id", employeeId));
        }
        Criteria critMotive = crit.createCriteria("feedbackMotive");
        if (projectId != null) {
            critMotive.add(Restrictions.eq("project.id", projectId));
        }
        if (roleId != null && !roleId.isEmpty()) {
            critFunctionEmp.add(Restrictions.eq("code", roleId));
        }
        if (mentorId != null) {
            critEmp.add(Restrictions.eq("mentor.id", mentorId));
        }
        if (evaluatorId != null) {
            crit.add(Restrictions.eq("feedback.reporter.id", evaluatorId));
        }
        if (jobFunctionWeightCurrentUser < 4) {
            crit.add(Restrictions.eq("feedback.reporter.id", employeeIdCurrentUser));
        }

        return crit.list();
    }

    @Override
    public boolean feedbackExist(final Long evaluatedId, final Long evaluatorId, final String projectName) {

        Criteria crit = getSession().createCriteria(Feedback.class, "feedback");

        if (evaluatedId != null) {
            crit.add(Restrictions.eq("feedback.evaluated.id", evaluatedId));
        }
        // Criteria critMotive = crit.createCriteria("feedbackMotive");
        // if (projectName != null) {
        // //critMotive.add(Restrictions.or(Restrictions.eq(propertyName,
        // value), rhs) eq("project.name", projectName));
        // DetachedCriteria manuallyValues =
        // DetachedCriteria.forClass(FeedbackMotiveManually.class);
        // manuallyValues.createCriteria("project").add(Restrictions.eq("project",
        // projectName));
        // DetachedCriteria proyectValues =
        // DetachedCriteria.forClass(FeedbackMotiveProject.class);
        // proyectValues.createCriteria("project").add(Restrictions.eq("project.name",
        // projectName));
        // Restrictions.or(Subqueries.in("project", bValues),
        // Subqueries.in("id", cValues));
        //
        // }
        if (evaluatorId != null) {
            crit.add(Restrictions.eq("feedback.reporter.id", evaluatorId));
        }
        Collection<Feedback> feedbacks = crit.list();
        for (Feedback feedback : feedbacks) {
            if (feedback.getFeedbackMotive().getProjectName().equalsIgnoreCase(projectName))
                return true;
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.hexacta.hrs.repositories.feedback.FeedbackRepository#
     * getPendingFeedbacksForRole(org.vectrics.recruiter.job.JobFunction)
     */
    @Override
    public List<Feedback> getPendingFeedbacksForRole(final String role, final Period period) {
        Criteria crit = getSession().createCriteria(Feedback.class, "feedback");

        crit.add(Restrictions.isNull("feedback.effort"));
        crit.add(Restrictions.isNull("feedback.score"));
        crit.add(Restrictions.eq("feedback.period", period.getYear()));
        crit.add(Restrictions.eq("feedback.closed", false));

        crit.add(Restrictions.eq("feedback.jobFunctionInProject.code", role));

        return crit.list();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.hexacta.hrs.repositories.feedback.FeedbackRepository#
     * getPendingFeedbacksForRole(com.hexacta.hrs.domain.feedback.Period)
     */
    @Override
    public List<Feedback> getPendingFeedbacks(final Period period) {
        Criteria crit = getSession().createCriteria(Feedback.class, "feedback");

        crit.add(Restrictions.isNull("feedback.effort"));
        crit.add(Restrictions.isNull("feedback.score"));
        crit.add(Restrictions.eq("feedback.period", period.getYear()));
        crit.add(Restrictions.eq("feedback.closed", false));

        return crit.list();
    }

}
